#include <iostream>
#include <string>

#include "./Include/dao_base.h"
#include "./Include/orm_mapper.h"

struct MyClass {
  int id;
  double score;
  std::string name;

  // visitor.Visit(fn, id, name, score);
  // *__FieldNames = "id, name, score"
  // const char *__ClassName = "MyClass";
  ORMAP(MyClass, id, name, score);
};

int main(int argc, char** argv) {
  DaoMyClass1 a;
  a.Insert(nullptr);
  ORMapper mapper("127.0.0.1", "root", "123456", "test", 3306);

  mapper.CreateTbl(MyClass{});

  std::vector<MyClass> initObjs = {
      {0, 0.2, "John"}, {1, 0.4, "Jack"}, {2, 0.6, "Jess"}};

  // Insert Values into the table
  for (const auto obj : initObjs) mapper.Insert(obj);
  std::cout << mapper.Query(MyClass{}).Count() << std::endl;
  // Update Entry by KEY (id)
  initObjs[1].score = 1.0;
  mapper.Update(initObjs[1]);

  // Delete Entry by KEY (id)
  mapper.Delete(initObjs[2]);

  // Transactional Statements
  try {
    mapper.Transaction([&]() {
      mapper.Delete(initObjs[0]);
      mapper.Insert(MyClass{4, 0, "abc"});
    });
  } catch (const std::exception& ex) {
    // ! catch 还未实现
    std::cout << "Transactional error;" << std::endl;
  }

  auto result1 = mapper.Query(MyClass{}).ToVector();
  std::vector<MyClass> dataToSeed;
  for (int i = 50; i < 100; i++)
    dataToSeed.emplace_back(MyClass{i, i * 0.2, "July"});
  mapper.InsertRange(dataToSeed);
  MyClass helper;
  auto result2 = mapper.Query(helper)
                     .Where(Field(helper.name) == "July" &&
                            (Field(helper.id) <= 90 && Field(helper.id) >= 60))
                     .ToVector();
  std::cout << result2.size() << std::endl;

  // Delete table by class
  mapper.DropTbl(MyClass{});

  return 0;
}
